package org.fhnw.aigs.server.common;
import java.io.File;
import java.io.IOException;
import java.util.logging.ConsoleHandler;
import java.util.logging.FileHandler;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
import org.fhnw.aigs.commons.XMLHelper;
/**
* Class to manage the server-side logging. It supersede standard logging for better control of the formats, outputs and levels of the logs.<br>
* The class uses the Java SE standard logger in the backend.<br>
* Possible log levels are Severe, Warning, System (messages of the AIGS server), Game (messages of AIGS games on the server) and Info.<br>
* v1.0 Inital release<br>
* v1.1 Fixed issues with malformed input for the xml logger
* @version 1.1
* @author Raphael Stoeckli (23.04.2015)
*/
public class LogRouter {
/**
* Singleton object of the logging threshold
*/
private static LoggingThreshold threshold = null;
/**
* Singleton object of the logging style
*/
private static LoggingStyle style = null;
/**
* Setter for the singleton instance of the logging threshold
* @param threshold Logging threshold
*/
public static void SetThreshold(LoggingThreshold threshold)
{
LogRouter.threshold = threshold;
}
/**
* Setter for the singleton instance of the logging style
* @param style Logging style
*/
public static void SetLoggerStyle(LoggingStyle style)
{
LogRouter.style = style;
}
/**
* Combined setter to update logging threshold and style
* @param threshold Logging threshold
* @param style Logging threshold
*/
public static void updateRules(LoggingThreshold threshold, LoggingStyle style)
{
LogRouter.threshold = threshold;
LogRouter.style = style;
}
/**
* Method to update logging threshold and style from the server configuration (settings)
*/
public static void updateRules()
{
LogRouter.updateRules(ServerConfiguration.getInstance().getLoggerThreshold(), ServerConfiguration.getInstance().getLoggerStyle());
}
/**
* This method is responsible for the logging by setting a FileHandler.
* Usually the log files will be saved to the folder "logs", under the name
* "aigs.log". Logs which exceed 10 MB in size will trigger the creation of
* a new logfile.
*/
public static void setUpLogging() {
// Get the standard logger (root logger) from which all loggers inherit
Logger rootLogger = Logger.getLogger("");
try {
// Creates "logs" folder, if it does not already exist
String logDirectory = ServerConfiguration.getInstance().getLogDirectory();
new File(logDirectory).mkdir();
//new File("logs").mkdir();
// Housekeeping: Get the old handlers and remove them.
Handler[] handlers = rootLogger.getHandlers();
for (Handler h : handlers) {
rootLogger.removeHandler(h);
}
// Add a filehandler to the root logger. All logging activity will
// be saved to the file "logs/aigs.log". If the file exceeds 10 MB
// a new file will be created (up to 10).
FileHandler fileHandler = new FileHandler(logDirectory + "/aigs.log", 1073741824, 10);
fileHandler.setEncoding("UTF-8");
// Decides which logging format will be used.
/*
if (ServerConfiguration.getInstance().getIsXMLlogging()) {
fileHandler.setFormatter(new XMLFormatter());
fileHandler.setLevel(Level.ALL);
} else {
fileHandler.setFormatter(new SimpleFormatter());
}
*/
fileHandler.setFormatter(new CustomFormatter(ServerConfiguration.getInstance().getLoggerStyle()));
fileHandler.setLevel(Level.ALL); // Filtering will be done adHoc in the log() method
rootLogger.addHandler(fileHandler);
// Add a Console handler so all logs will also be shown on the console.
ConsoleHandler consoleHandler = new ConsoleHandler();
consoleHandler.setLevel(Level.ALL);
consoleHandler.setFormatter(new SimpleFormatter());
rootLogger.addHandler(consoleHandler);
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, "File could not be opened or created. A new log file will be created.", ex);
} catch (SecurityException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
catch (Exception ex) // All other exceptions
{
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, "An unknown error occured.", ex);
}
Logger.getLogger(Main.class.getName()).log(Level.INFO, "Now logging...");
}
/**
* Method to process a log entry
* @param className Name of the calling class
* @param level Logging level of the entry
* @param customMessage Message, can contain {0} which will be resolved with the content of the parameter (param)
* @param param Parameter of the log entry
*/
public static void log(String className, LoggingLevel level, String customMessage, Object param)
{
if (LogRouter.threshold == null) // Init (store threshold for better performance)
{
LogRouter.threshold = ServerConfiguration.getInstance().getLoggerThreshold();
}
if (LogRouter.style == null) // Init (store style for better performance)
{
LogRouter.style = ServerConfiguration.getInstance().getLoggerStyle();
}
customMessage = processMessage(customMessage);
if (LogRouter.threshold == LoggingThreshold.off || level == LoggingLevel.none) { return; } // Discard
else if (LogRouter.threshold == LoggingThreshold.all) // Sys, severe, warn, info
{
if (level == LoggingLevel.severe)
{
Logger.getLogger(className).log(Level.SEVERE, customMessage, param);
}
else if (level == LoggingLevel.waring)
{
Logger.getLogger(className).log(Level.WARNING, customMessage, param);
}
else //if (level == LoggingLevel.info) // Info
{
Logger.getLogger(className).log(Level.INFO, customMessage, param);
}
}
else if (LogRouter.threshold == LoggingThreshold.warningSevereSystemGame) // Game, Sys, severe, warn
{
if (level == LoggingLevel.severe)
{
Logger.getLogger(className).log(Level.SEVERE, customMessage, param);
}
else if (level == LoggingLevel.waring)
{
Logger.getLogger(className).log(Level.WARNING, customMessage, param);
}
else if (level == LoggingLevel.system)
{
Logger.getLogger(className).log(Level.INFO, customMessage, param);
}
else if (level == LoggingLevel.game)
{
Logger.getLogger(className).log(Level.INFO, customMessage, param);
}
}
else if (LogRouter.threshold == LoggingThreshold.warningSevereSystem) // Sys, severe, warn
{
if (level == LoggingLevel.severe)
{
Logger.getLogger(className).log(Level.SEVERE, customMessage, param);
}
else if (level == LoggingLevel.waring)
{
Logger.getLogger(className).log(Level.WARNING, customMessage, param);
}
else if (level == LoggingLevel.system)
{
Logger.getLogger(className).log(Level.INFO, customMessage, param);
}
}
else if (LogRouter.threshold == LoggingThreshold.waringSevere) // Severe, warn
{
if (level == LoggingLevel.severe)
{
Logger.getLogger(className).log(Level.SEVERE, customMessage, param);
}
else if (level == LoggingLevel.waring)
{
Logger.getLogger(className).log(Level.WARNING, customMessage, param);
}
}
else if (LogRouter.threshold == LoggingThreshold.severeSystem) // Sys, severe
{
if (level == LoggingLevel.severe)
{
Logger.getLogger(className).log(Level.SEVERE, customMessage, param);
}
else if (level == LoggingLevel.system)
{
Logger.getLogger(className).log(Level.INFO, customMessage, param);
}
}
else if (LogRouter.threshold == LoggingThreshold.severeSystemGame) // Game, Sys, severe
{
if (level == LoggingLevel.severe)
{
Logger.getLogger(className).log(Level.SEVERE, customMessage, param);
}
else if (level == LoggingLevel.system)
{
Logger.getLogger(className).log(Level.INFO, customMessage, param);
}
else if (level == LoggingLevel.game)
{
Logger.getLogger(className).log(Level.INFO, customMessage, param);
}
}
else if (LogRouter.threshold == LoggingThreshold.severe) // Severe
{
if (level == LoggingLevel.severe)
{
Logger.getLogger(className).log(Level.SEVERE, customMessage, param);
}
}
else if (LogRouter.threshold == LoggingThreshold.system) // Sys
{
if (level == LoggingLevel.system)
{
Logger.getLogger(className).log(Level.INFO, customMessage, param);
}
}
else if (LogRouter.threshold == LoggingThreshold.game) // Game
{
if (level == LoggingLevel.game)
{
Logger.getLogger(className).log(Level.INFO, customMessage, param);
}
}
}
/**
* Method to process a log entry
* @param className Name of the calling class
* @param level Logging level of the entry
* @param customMessage Message, can contain {NUMBERS} which will be resolved with the content of the parameters (params)
* @param params Array of parameter of the log entry
*/
public static void log(String className, LoggingLevel level, String customMessage, Object[] params)
{
if (LogRouter.threshold == null) // Init (store threshold for better performance)
{
LogRouter.threshold = ServerConfiguration.getInstance().getLoggerThreshold();
}
if (LogRouter.style == null) // Init (store style for better performance)
{
LogRouter.style = ServerConfiguration.getInstance().getLoggerStyle();
}
customMessage = processMessage(customMessage);
if (LogRouter.threshold == LoggingThreshold.off || level == LoggingLevel.none) { return; } // Discard
else if (LogRouter.threshold == LoggingThreshold.all) // Sys, severe, warn, info
{
if (level == LoggingLevel.severe)
{
Logger.getLogger(className).log(Level.SEVERE, customMessage, params);
}
else if (level == LoggingLevel.waring)
{
Logger.getLogger(className).log(Level.WARNING, customMessage, params);
}
else //if (level == LoggingLevel.info) // Info
{
Logger.getLogger(className).log(Level.INFO, customMessage, params);
}
}
else if (LogRouter.threshold == LoggingThreshold.warningSevereSystemGame) // Game, Sys, severe, warn
{
if (level == LoggingLevel.severe)
{
Logger.getLogger(className).log(Level.SEVERE, customMessage, params);
}
else if (level == LoggingLevel.waring)
{
Logger.getLogger(className).log(Level.WARNING, customMessage, params);
}
else if (level == LoggingLevel.system)
{
Logger.getLogger(className).log(Level.INFO, customMessage, params);
}
else if (level == LoggingLevel.game)
{
Logger.getLogger(className).log(Level.INFO, customMessage, params);
}
}
else if (LogRouter.threshold == LoggingThreshold.warningSevereSystem) // Sys, severe, warn
{
if (level == LoggingLevel.severe)
{
Logger.getLogger(className).log(Level.SEVERE, customMessage, params);
}
else if (level == LoggingLevel.waring)
{
Logger.getLogger(className).log(Level.WARNING, customMessage, params);
}
else if (level == LoggingLevel.system)
{
Logger.getLogger(className).log(Level.INFO, customMessage, params);
}
}
else if (LogRouter.threshold == LoggingThreshold.waringSevere) // Severe, warn
{
if (level == LoggingLevel.severe)
{
Logger.getLogger(className).log(Level.SEVERE, customMessage, params);
}
else if (level == LoggingLevel.waring)
{
Logger.getLogger(className).log(Level.WARNING, customMessage, params);
}
}
else if (LogRouter.threshold == LoggingThreshold.severeSystem) // Sys, severe
{
if (level == LoggingLevel.severe)
{
Logger.getLogger(className).log(Level.SEVERE, customMessage, params);
}
else if (level == LoggingLevel.system)
{
Logger.getLogger(className).log(Level.INFO, customMessage, params);
}
}
else if (LogRouter.threshold == LoggingThreshold.severeSystemGame) // Game, Sys, severe
{
if (level == LoggingLevel.severe)
{
Logger.getLogger(className).log(Level.SEVERE, customMessage, params);
}
else if (level == LoggingLevel.system)
{
Logger.getLogger(className).log(Level.INFO, customMessage, params);
}
else if (level == LoggingLevel.game)
{
Logger.getLogger(className).log(Level.INFO, customMessage, params);
}
}
else if (LogRouter.threshold == LoggingThreshold.severe) // Severe
{
if (level == LoggingLevel.severe)
{
Logger.getLogger(className).log(Level.SEVERE, customMessage, params);
}
}
else if (LogRouter.threshold == LoggingThreshold.system) // Sys
{
if (level == LoggingLevel.system)
{
Logger.getLogger(className).log(Level.INFO, customMessage, params);
}
}
else if (LogRouter.threshold == LoggingThreshold.game) // Game
{
if (level == LoggingLevel.game)
{
Logger.getLogger(className).log(Level.INFO, customMessage, params);
}
}
}
/**
* Method to process a log entry
* @param className Name of the calling class
* @param level Logging level of the entry
* @param customMessage Message to display (no further parameters)
*/
public static void log(String className, LoggingLevel level, String customMessage)
{
if (LogRouter.threshold == null) // Init (store threshold for better performance)
{
LogRouter.threshold = ServerConfiguration.getInstance().getLoggerThreshold();
}
if (LogRouter.style == null) // Init (store style for better performance)
{
LogRouter.style = ServerConfiguration.getInstance().getLoggerStyle();
}
customMessage = processMessage(customMessage);
if (LogRouter.threshold == LoggingThreshold.off || level == LoggingLevel.none) { return; } // Discard
else if (LogRouter.threshold == LoggingThreshold.all) // Sys, severe, warn, info
{
if (level == LoggingLevel.severe)
{
Logger.getLogger(className).log(Level.SEVERE, customMessage);
}
else if (level == LoggingLevel.waring)
{
Logger.getLogger(className).log(Level.WARNING, customMessage);
}
else //if (level == LoggingLevel.info) // Info
{
Logger.getLogger(className).log(Level.INFO, customMessage);
}
}
else if (LogRouter.threshold == LoggingThreshold.warningSevereSystemGame) // Game, Sys, severe, warn
{
if (level == LoggingLevel.severe)
{
Logger.getLogger(className).log(Level.SEVERE, customMessage);
}
else if (level == LoggingLevel.waring)
{
Logger.getLogger(className).log(Level.WARNING, customMessage);
}
else if (level == LoggingLevel.system)
{
Logger.getLogger(className).log(Level.INFO, customMessage);
}
else if (level == LoggingLevel.game)
{
Logger.getLogger(className).log(Level.INFO, customMessage);
}
}
else if (LogRouter.threshold == LoggingThreshold.warningSevereSystem) // Sys, severe, warn
{
if (level == LoggingLevel.severe)
{
Logger.getLogger(className).log(Level.SEVERE, customMessage);
}
else if (level == LoggingLevel.waring)
{
Logger.getLogger(className).log(Level.WARNING, customMessage);
}
else if (level == LoggingLevel.system)
{
Logger.getLogger(className).log(Level.INFO, customMessage);
}
}
else if (LogRouter.threshold == LoggingThreshold.waringSevere) // Severe, warn
{
if (level == LoggingLevel.severe)
{
Logger.getLogger(className).log(Level.SEVERE, customMessage);
}
else if (level == LoggingLevel.waring)
{
Logger.getLogger(className).log(Level.WARNING, customMessage);
}
}
else if (LogRouter.threshold == LoggingThreshold.severeSystem) // Sys, severe
{
if (level == LoggingLevel.severe)
{
Logger.getLogger(className).log(Level.SEVERE, customMessage);
}
else if (level == LoggingLevel.system)
{
Logger.getLogger(className).log(Level.INFO, customMessage);
}
}
else if (LogRouter.threshold == LoggingThreshold.severeSystemGame) // Game, Sys, severe
{
if (level == LoggingLevel.severe)
{
Logger.getLogger(className).log(Level.SEVERE, customMessage);
}
else if (level == LoggingLevel.system)
{
Logger.getLogger(className).log(Level.INFO, customMessage);
}
else if (level == LoggingLevel.game)
{
Logger.getLogger(className).log(Level.INFO, customMessage);
}
}
else if (LogRouter.threshold == LoggingThreshold.severe) // Severe
{
if (level == LoggingLevel.severe)
{
Logger.getLogger(className).log(Level.SEVERE, customMessage);
}
}
else if (LogRouter.threshold == LoggingThreshold.system) // Sys
{
if (level == LoggingLevel.system)
{
Logger.getLogger(className).log(Level.INFO, customMessage);
}
}
else if (LogRouter.threshold == LoggingThreshold.game) // Game
{
if (level == LoggingLevel.game)
{
Logger.getLogger(className).log(Level.INFO, customMessage);
}
}
}
/**
* Method to route the custom message. In case of XML style, {@link XMLHelper#prettyPrintXml(java.lang.String)} will be used.
* Otherwise the input will not be changed. In case of the style "discard" an empty string will be returned.
* @param input Message to process
* @return Processed message
*/
private static String processMessage(String input)
{
if (input == null) { return null;}
if (LogRouter.style == LoggingStyle.discard){ return "";}
else if ( LogRouter.style == LoggingStyle.compressed) { return input; }
else if ( LogRouter.style == LoggingStyle.xmlFull || LogRouter.style == LoggingStyle.plainFull )
{
return input;
}
else
{
return XMLHelper.prettyPrintXml(input, true); // Discard transformation errors and return plain text
}
}
}